<template>
  <div class="view-tabs">
    <div class="viewTabsMoveIcon">
      <i class="el-icon-arrow-left moveLeftIcon" @click="moveLeftTabBar"></i>
    </div>
    <div class="viewTabsMain" ref="viewTabsMain">
      <div
        v-for="(item, index) in tabs"
        :label="item.title"
        :name="item.tabKey"
        :key="item.tabKey"
        :class="[
          'viewTabsItem',
          curTabKey === item.tabKey ? 'viewTabsItemSelected ' : '',
        ]"
      >
        <div class="viewTabsItemText" @click="clickTab(index)">
          <span>
            {{ item.title }}
          </span>
        </div>
        <div class="viewTabsItemIcon" v-if="curTabKey === item.tabKey">
          <i class="el-icon-refresh" @click="refreshTab(item)"></i>
        </div>
        <div class="viewTabsItemIcon">
          <i class="el-icon-close" @click="removeTab(item.tabKey)"></i>
        </div>
      </div>
    </div>
    <div class="viewTabsMoveIcon">
      <i
        class="el-icon-circle-close closeIcon"
        style="height: 100%"
        @click="closeOtherTabs"
      ></i>
    </div>
    <div class="viewTabsMoveIcon">
      <i class="el-icon-arrow-right moveRightIcon" @click="moveRightTabBar"></i>
    </div>
  </div>
</template>

<script>
import { mapMutations, mapActions } from 'vuex';
import EventBus from '@/eventBus';
export default {
  name: 'ViewTabButtons',
  props: {
    // 【根据项目修改】tab页面在路由的第几层，或者说第几层的 router-view 组件（当前项目为第二层）
    tabRouteViewDepth: {
      type: Number,
      default: 2,
    },
    // tab页面的key值，从route对象中取，一个key值对应一个tab页面
    // 默认为matchRoute.path值
    getTabKey: {
      type: Function,
      default: function (routeMatch /* , route */) {
        return routeMatch.path;
      },
    },
    // tab页签的标题，默认从路由meta.title中获取
    tabTitleKey: {
      type: String,
      default: 'title',
    },
  },
  data() {
    return {
      tabs: [],
      curTabKey: '',
    };
  },

  methods: {
    ...mapActions('cache', ['addCache', 'removeCache', 'removeCacheEntry']),
    ...mapMutations(['setIsRenderTab']),
    // 切换tab
    changeCurTab() {
      // 当前路由信息
      const { path, query, params, hash, matched } = this.$route;
      // tab标签页路由信息：meta、componentName
      const routeMatch = matched[this.tabRouteViewDepth - 1];
      const meta = routeMatch.meta;
      const componentName = routeMatch.components?.default?.name;
      // 获取tab标签页信息：tabKey标签页key值；title-标签页标题；tab-存在的标签页
      const tabKey = this.getTabKey(routeMatch, this.$route);
      const title = String(meta[this.tabTitleKey] || '');
      const tab = this.tabs.find((tab) => tab.tabKey === tabKey);
      const index = this.tabs.findIndex((tab) => tab.tabKey === tabKey);

      if (!tabKey) {
        // tabKey默认为路由的name值
        console.warn(
          `LayoutTabs组件：${path} 路由没有匹配的tab标签页，如有需要请配置tab标签页的key值`,
        );
        return;
      }

      // 如果同一tab路径变了（例如路径为 /detail/:id），则清除缓存实例
      if (tab && tab.path !== path) {
        this.removeCacheEntry(componentName || '');
        tab.title = '';
      }

      const newTab = {
        tabKey,
        title: tab?.title || title,
        path,
        params,
        query,
        hash,
        componentName,
      };
      tab ? Object.assign(tab, newTab) : this.tabs.push(newTab);
      this.curTabKey = tabKey;
      if (tab) {
        this.$refs.viewTabsMain.scrollLeft = index * 190;
      } else {
        this.$nextTick(function () {
          this.$refs.viewTabsMain.scrollLeft =
            this.$refs.viewTabsMain.scrollWidth;
          console.log('当前滚动条位置:' + this.$refs.viewTabsMain.scrollLeft);
          console.log(
            '当前可滚动区域容器的高度:' + this.$refs.viewTabsMain.scrollWidth,
          );
        });
      }
    },
    // 点击tab
    clickTab(index) {
      //if (!pane.index) return;

      const tab = this.tabs[Number(index)];
      if (tab.path !== this.$route.path) {
        this.gotoTab(tab);
      }
    },
    // 移除tab
    async removeTab(tabKey) {
      console.log(tabKey);
      // 剩下一个时不能删
      if (this.tabs.length === 1) return;

      const index = this.tabs.findIndex((tab) => tab.tabKey === tabKey);
      if (index < -1) return;

      const tab = this.tabs[index];
      this.tabs.splice(index, 1);

      // 如果删除的是当前tab，则切换到最后一个tab
      if (tab.tabKey === this.curTabKey) {
        const lastTab = this.tabs[this.tabs.length - 1];
        lastTab && this.gotoTab(lastTab);
      }
      this.removeCache(tab.componentName || '');
    },
    // 跳转tab页面
    async gotoTab(tab) {
      await this.$router.push({
        path: tab.path,
        query: tab.query,
        hash: tab.hash,
      });
    },
    // 关闭非当前页的所有tab页签
    closeOtherTabs() {
      this.tabs
        .filter((tab) => tab.tabKey !== this.curTabKey)
        .forEach((tab) => {
          this.removeCache(tab.componentName || '');
        });
      this.tabs = this.tabs.filter((tab) => tab.tabKey === this.curTabKey);
    },
    // 刷新当前tab页面
    async refreshTab(tab) {
      this.setIsRenderTab(false);
      await this.removeCacheEntry(tab.componentName);
      this.setIsRenderTab(true);
    },
    // 关闭tab页面，默认关闭当前页
    async closeLayoutTab(tabKey = this.curTabKey) {
      const index = this.tabs.findIndex((tab) => tab.tabKey === tabKey);
      if (index > -1) {
        this.removeCache(this.tabs[index].componentName);
        this.tabs.splice(index, 1);
      }
    },
    // 设置当前tab的标题
    setCurTabTitle(title) {
      const curTab = this.tabs.find((tab) => tab.tabKey === this.curTabKey);
      if (curTab) {
        curTab.title = title;
      }
    },
    moveLeftTabBar() {
      this.$refs.viewTabsMain.scrollLeft =
        this.$refs.viewTabsMain.scrollLeft - 190;
    },
    moveRightTabBar() {
      this.$refs.viewTabsMain.scrollLeft =
        this.$refs.viewTabsMain.scrollLeft + 190;
    },
  },
  watch: {
    '$route.path': {
      handler() {
        this.changeCurTab();
      },
      immediate: true,
    },
  },
  created() {
    // 对外提供的事件：关闭弹窗；设置tab标题
    EventBus.$on('LayoutTabs:closeTab', (tabKey) => {
      this.closeLayoutTab(tabKey);
    });
    EventBus.$on('LayoutTabs:setTabTitle', (title) => {
      this.setCurTabTitle(title);
    });
  },
};
</script>
<style scoped>
.view-tabs {
  flex: 1;
  display: flex;
  flex-direction: row;
  padding: 0px;
  text-align: center;
  border-radius: 25px;
  background-color: white;
  border: 1px solid #ebeef5;
  box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
}
.viewTabsMoveIcon {
  min-width: 20px;
  min-height: 45px;
  cursor: pointer;
  font-size: 1.5em;
  color: #606266;
  display: flex;
  align-items: center;
  justify-content: center;
}
.viewTabsMoveIcon :hover {
  color: #409eff;
  background-color: #edf5ff;
}

.viewTabsMain {
  flex: 1;
  width: 0;
  display: flex;
  overflow-x: auto;
  padding: 5px;
  font-size: 1.1em;
  font-weight: 500;
}

.viewTabsItem {
  min-width: 190px;
  min-height: 35px;
  margin-left: 5px;
  background-color: #fafafa;
  color: #1f1f1f;
  border-radius: 5px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  border: 1px solid #dcdfe6;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 2px 0 rgba(0, 0, 0, 0.19);
  /* box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); */
}
.viewTabsItem :hover {
  background-color: #80d8ff;
}
.viewTabsItemSelected {
  background-color: #4fc3f7;
  /* //color: #fff; */
  border: 1px solid #4fc3f7;
}
.viewTabsItemSelected :hover {
  background-color: #03a9f4;
}
.viewTabsItemText {
  flex: 1;
  overflow-x: hidden;
  white-space: nowrap;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.viewTabsItemIcon {
  min-width: 25px;
  height: 100%;
  margin-left: 2px;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
.closeIcon {
  min-width: 25px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.moveLeftIcon {
  min-width: 20px;
  height: 100%;
  border-top-left-radius: 20px;
  border-bottom-left-radius: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.moveRightIcon {
  min-width: 20px;
  height: 100%;
  border-top-right-radius: 20px;
  border-bottom-right-radius: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
